import numpy as np
import matplotlib.pyplot as plt


def plot_prediction(actual, predicted, title='RNN Prediction'):
    """
    绘制预测结果对比图

    参数:
    actual -- 实际值序列
    predicted -- 预测值序列
    title -- 图表标题
    """
    plt.figure(figsize=(12, 6))
    plt.plot(actual, label='实际值')
    plt.plot(predicted, label='预测值')
    plt.legend()
    plt.title(title)
    plt.xlabel('时间步')
    plt.ylabel('值')
    plt.grid(True)
    return plt


def plot_loss(loss_history, title='训练损失曲线'):
    """
    绘制训练损失曲线

    参数:
    loss_history -- 损失历史记录
    title -- 图表标题
    """
    plt.figure(figsize=(10, 5))
    plt.plot(loss_history)
    plt.title(title)
    plt.xlabel('迭代次数')
    plt.ylabel('损失')
    plt.grid(True)
    return plt


def generate_data(data_type='sine', samples=200, period=20, amplitude=1.0, noise=0.0):
    """
    生成不同类型的时序数据

    参数:
    data_type -- 数据类型: 'sine'正弦波, 'square'方波, 'triangle'三角波
    samples -- 样本数量
    period -- 周期
    amplitude -- 振幅
    noise -- 噪声水平

    返回:
    data -- 生成的数据
    """
    x = np.linspace(0, samples / period * 2 * np.pi, samples)

    if data_type == 'sine':
        data = amplitude * np.sin(x)
    elif data_type == 'square':
        data = amplitude * np.sign(np.sin(x))
    elif data_type == 'triangle':
        data = amplitude * (2 / np.pi) * np.arcsin(np.sin(x))
    else:
        raise ValueError(f"不支持的数据类型: {data_type}")

    # 添加噪声
    if noise > 0:
        data += np.random.normal(0, noise, size=samples)

    return data


def normalize_data(data):
    """
    数据归一化

    参数:
    data -- 原始数据

    返回:
    normalized_data -- 归一化后的数据
    data_min -- 最小值
    data_max -- 最大值
    """
    data_min = np.min(data)
    data_max = np.max(data)
    normalized_data = (data - data_min) / (data_max - data_min)
    return normalized_data, data_min, data_max


def denormalize_data(normalized_data, data_min, data_max):
    """
    数据反归一化

    参数:
    normalized_data -- 归一化后的数据
    data_min -- 最小值
    data_max -- 最大值

    返回:
    data -- 原始数据范围
    """
    return normalized_data * (data_max - data_min) + data_min